home *** CD-ROM | disk | FTP | other *** search
/ Die Speccy' 97 / Die Speccy' 97.iso / amiga_system / the_aminet / util / boot / snap_v2_0.lha / Snap / SaveILBM.c < prev    next >
C/C++ Source or Header  |  1995-09-10  |  5KB  |  238 lines

  1. /* Auto: make
  2.  */
  3.  
  4. #include <setjmp.h>
  5.  
  6. #include "Snap.h"
  7.  
  8. #define SAFE( cond, jmp_buf)  { if ( !( cond)) longjmp( jmp_buf,-1); }
  9.  
  10. IMPORT BYTE TranspBuf[ ];
  11.  
  12. #define ID( a,b,c,d) ( ( a << 24L) | ( b << 16L) | ( c << 8L) | ( d))
  13.  
  14. struct ckHdr
  15. {
  16.     LONG ChunkName;
  17.     LONG ChunkSize;
  18. };
  19.  
  20. struct SnapBitMapHeader
  21. {
  22.     UWORD w, h;
  23.     WORD x, y;
  24.     UBYTE nPlanes;
  25.     UBYTE masking;
  26.     UBYTE compression;
  27.     UBYTE pad1;
  28.     UWORD transparentColor;
  29.     UBYTE xAspect, yAspect;
  30.     WORD pageWidth, pageHeight;
  31. };
  32.  
  33. struct ckHdr FORM =
  34. {
  35.     ID( 'F', 'O', 'R', 'M'),
  36.     0L
  37. };
  38. LONG TYPE = ID( 'I', 'L', 'B', 'M');
  39.  
  40. struct ckHdr BMHD =
  41. {
  42.     ID( 'B', 'M', 'H', 'D'),
  43.     sizeof ( struct SnapBitMapHeader)
  44. };
  45. struct SnapBitMapHeader BMHdr =
  46. {
  47.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  48. };
  49.  
  50. struct ckHdr CAMG =
  51. {
  52.     ID( 'C', 'A', 'M', 'G'),
  53.     4L
  54. };
  55. ULONG ViewMode = NULL;
  56.  
  57. struct ckHdr CMAP =
  58. {
  59.     ID( 'C', 'M', 'A', 'P'),
  60.     0L
  61. };
  62.  
  63. struct ckHdr BODY =
  64. {
  65.     ID( 'B', 'O', 'D', 'Y'),
  66.     0L
  67. };
  68.  
  69. UBYTE *buf;
  70. WORD bufcnt;
  71. ULONG totalsize;
  72.  
  73. WORD bump( struct CBFHandle *CBFH, WORD cnt, UBYTE * dataptr, WORD size)
  74. {
  75.     REGISTER LONG tsize = size;
  76.  
  77.     if ( tsize)
  78.     {
  79.         totalsize += tsize + 1;        /* Don't forget the count-byte */
  80.     }
  81.     if ( bufcnt + tsize + 1 >= 4096 || tsize == 0)
  82.     {
  83.         if ( CBFWrite( CBFH, ( char *)buf, ( LONG) bufcnt) == -1L)
  84.         {
  85.             return 0;
  86.         }
  87.         bufcnt = 0;
  88.     }
  89.     buf[ bufcnt++] = cnt;
  90.     CopyMem( ( char *)dataptr, ( char *)&buf[ bufcnt], tsize);
  91.     bufcnt += tsize;
  92.     return 1;
  93. }
  94.  
  95. ULONG WriteBody( BM, CBFH)
  96.     struct BitMap *BM;
  97.     struct CBFHandle *CBFH;
  98. {
  99.     WORD scanline, plane;
  100.     REGISTER WORD bpr = BM->BytesPerRow;
  101.     REGISTER WORD i, j;
  102.     LONG offset = 0L;
  103.     REGISTER UBYTE data;
  104.     REGISTER UBYTE *bd;
  105.     jmp_buf failure;
  106.  
  107.     totalsize = 0L;
  108.  
  109.     if ( !( buf = AllocMem( 4096L, MEMF_PUBLIC)))
  110.     {
  111.         return NULL;
  112.     }
  113.  
  114.     if ( setjmp( failure))
  115.     {
  116.         FreeMem( buf, 4096L);
  117.         return NULL;
  118.     }
  119.  
  120.     bufcnt = 0;
  121.     for ( scanline = 0; scanline < BM->Rows; ++scanline)
  122.     {
  123.         for ( plane = 0; plane < BM->Depth; ++plane)
  124.         {
  125.             bd = BM->Planes[ plane] + offset;
  126.             i = 1;
  127.             j = bpr - 1;
  128.             data = bd[ 0];
  129.             while ( j)
  130.             {
  131.                 if ( bd[ i] == data)
  132.                 {    /* Equal bytes? */
  133.                     --i;    /* First equal byte */
  134.                     if ( i > 0)
  135.                     {    /* Old "random" data to save */
  136.                         SAFE( bump( CBFH, ( WORD) ( i - 1), bd, i), failure);
  137.                     }
  138.                     bd = &bd[ i];    /* Start of equal bytes */
  139.                     i = 2;    /* 0 & 1 is equal       */
  140.                     --j;
  141.                     while ( i < 128 && j && bd[ i] == data)
  142.                     {
  143.                         ++i;
  144.                         --j;
  145.                     }
  146.                     SAFE( bump( CBFH, ( WORD) - ( i - 1), &bd[ i - 1], ( WORD) 1), failure);
  147.                     goto new_block;
  148.                 }
  149.                 else
  150.                 {    /* Not equal. Check block range */
  151.                     if ( i == 128)
  152.                     {    /* Block limit                  */
  153.                         SAFE( bump( CBFH, ( WORD) ( i - 1), bd, i), failure);
  154.                           new_block:
  155.                         bd = &bd[ i];    /* Start new block              */
  156.                         i = 0;
  157.                         if ( j == 0)
  158.                         {
  159.                             break;
  160.                         }
  161.                     }
  162.                 }
  163.                 /* Different byte or a new start */
  164.                 data = bd[ i];    /* New possible equal       */
  165.                   next_byte:
  166.                 ++i;
  167.                 --j;
  168.             }
  169.             if ( i != 0)
  170.             {    /* Data to save */
  171.                 SAFE( bump( CBFH, ( WORD) ( i - 1), bd, i), failure);
  172.             }
  173.         }
  174.         offset += BM->BytesPerRow;
  175.     }
  176.     /* Flush any bytes left if the buffer */
  177.     SAFE( bump( CBFH, ( WORD) 0, NULL, ( WORD) 0), failure);
  178.     FreeMem( buf, 4096L);
  179.     return totalsize;
  180. }
  181.  
  182. WORD SaveGS( GS, CBFH)
  183.     struct GfxSnap *GS;
  184.     struct CBFHandle *CBFH;
  185. {
  186.     ULONG BODYPos;
  187.     UBYTE *oldtitle;
  188.     jmp_buf failure;
  189.  
  190.     oldtitle = GS->window->Title;
  191.     SetWindowTitles( GS->window, "Saving...", ( char *)-1);
  192.  
  193.     BMHdr.w = GS->BitMap->BytesPerRow * 8;
  194.     BMHdr.h = GS->height;
  195.     BMHdr.x = BMHdr.y = 0;
  196.     BMHdr.nPlanes = GS->depth;
  197.     BMHdr.masking = 0;
  198.     BMHdr.compression = 1;
  199.     BMHdr.transparentColor = dectoint( TranspBuf);
  200.     BMHdr.xAspect = BMHdr.xAspect = 1;
  201.     BMHdr.pageWidth = GS->pagew;
  202.     BMHdr.pageHeight = GS->pageh;
  203.     ViewMode = GS->viewmode;
  204.  
  205.     CMAP.ChunkSize = ( LONG) 3 *( GS->viewmode & HAM ? 16 : 1L << GS->depth);
  206.  
  207.     CBFInit( CBFH);
  208.  
  209.     if ( setjmp( failure))
  210.     {
  211.         CBFEndWrite( CBFH);
  212.         return 0;
  213.     }
  214.  
  215.     SAFE( CBFWrite( CBFH, ( char *)&FORM,
  216.               ( LONG) ( sizeof ( FORM) + sizeof ( TYPE) +
  217.                   sizeof ( BMHD) + sizeof ( BMHdr) +
  218.                   sizeof ( CAMG) + sizeof ( ViewMode) +
  219.                   sizeof ( CMAP))) != -1L, failure);
  220.     SAFE( CBFWrite( CBFH, ( char *)GS->rgb, CMAP.ChunkSize) != -1L, failure);
  221.     BODYPos = CBFSeek( CBFH, 0L, OFFSET_CURRENT);
  222.     SAFE( CBFWrite( CBFH, ( char *)&BODY, ( LONG) sizeof ( BODY)) != -1L, failure);
  223.     SAFE( BODY.ChunkSize = WriteBody( GS->BitMap, CBFH), failure);
  224.     FORM.ChunkSize = BODYPos - sizeof ( FORM) + sizeof ( BODY) + BODY.ChunkSize;
  225.     if ( FORM.ChunkSize & 1)
  226.     {            /* Odd size */
  227.         SAFE( CBFWrite( CBFH, "X", 1L) != -1L, failure);
  228.         ++FORM.ChunkSize;
  229.     }
  230.     CBFSeek( CBFH, 0L, OFFSET_BEGINNING);
  231.     CBFWrite( CBFH, ( char *)&FORM, ( LONG) sizeof ( FORM));
  232.     CBFSeek( CBFH, BODYPos, OFFSET_BEGINNING);
  233.     CBFWrite( CBFH, ( char *)&BODY, ( LONG) sizeof ( BODY));
  234.     CBFEndWrite( CBFH);
  235.     SetWindowTitles( GS->window, ( char *)oldtitle, ( char *)-1);
  236.     return 1;
  237. }
  238.